/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						         font.h

	$Header: /resource_editor/font.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef FONT_H_INCLUDED
#define FONT_H_INCLUDED

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <assert.h>
#include <vector>
#include "abstract_bitmap.h"
#include "resource_traits.h"

class t_string_vector;
// -------------------------------------------------------------
// bitmap class for holding character image for a font
// -------------------------------------------------------------
class t_font_bitmap : public t_abstract_bitmap8
{
public:
	void create( int width, int height, int leading_space, int trailing_space );
	void draw_to( t_abstract_bitmap16& bitmap, t_screen_point point, t_uint16 color,
		          bool drop_shadow, t_uint16 drop_shadow_color ) const;
	int  get_leading_space() const;
	int  get_trailing_space() const;
	bool read( std::streambuf& buffer, int version );
	bool write( std::streambuf& buffer ) const;
protected:
	int                  m_leading_space;
	int                  m_trailing_space;
	std::vector<t_uint8> m_image;
};


// -------------------------------------------------------------
// inlines for t_font_bitmap
// -------------------------------------------------------------
inline int t_font_bitmap::get_leading_space() const
{
	return m_leading_space;
}

inline int t_font_bitmap::get_trailing_space() const
{
	return m_trailing_space;
}

// -------------------------------------------------------------
// font class
// -------------------------------------------------------------
class t_font
{
public:
	t_font();
	t_font( int first_character, int height, int max_width, int baseline, int size );
	virtual ~t_font();

//	void draw_to( t_abstract_bitmap16& bitmap, t_screen_point point,
//		          char const* text, t_uint16 color = 0, bool drop_shadow = true,
//				  t_uint16 drop_shadow_color = 0) const;
	void draw_to( t_abstract_bitmap16& bitmap, t_screen_point point,
		          char const* text, t_uint16 color = 0, bool drop_shadow = true,
				  t_uint16 drop_shadow_color = 0,UINT pown = 0, int line=0);
	// draw text, wrapped to fit the rectangle
	void draw_to( t_abstract_bitmap16& bitmap, t_screen_rect const& rect, char const* text,
		          t_uint16 color = 0, bool drop_shadow = true,
				  t_uint16 drop_shadow_color = 0 ) const;
    // draw pre-wrapped text to a given rectangle
	void draw_to( t_abstract_bitmap16& bitmap, t_screen_rect const& rect, 
		          t_string_vector const& text, t_uint16 color = 0, bool drop_shadow = true,
				  t_uint16 drop_shadow_color = 0 ) const;

	int            get_baseline() const;
	t_font_bitmap* get_character( t_uint8 character ) const;
	int            get_column( char const* text, int x ) const;
	int            get_first_character() const;
	int            get_height() const;
	int            get_last_character() const;
	int            get_max_width() const;
	t_screen_rect  get_rect( char const* text ) const;
	int            get_size() const;
	int            get_width( char const* text ) const;
	int            get_wrapped_height( char const* text, int width ) const;
	int            longest_word_length( char const* text ) const;
	bool           read( std::streambuf& buffer );
	// wrap text so that it is no longer than "width" wide.
	// returns actual width in pixels.
	int            wrap_text( t_string_vector& result, char const* text, int width ) const;
	// wrap text so that it is no longer than "width" wide, but allow narrower
	// results to allow better proportions.
	int            wrap_text( t_string_vector& result, char const* text, int width, 
		                      int max_width ) const;
	bool           write( std::streambuf& buffer ) const;

protected:

	int m_baseline; // offset to base of characters
	int m_first_character;
	int m_max_width;
	int m_size;
	t_font_bitmap* m_characters;


public:
	UINT			 m_pown[50];

	int m_height;
	int	m_width;

	HDC		 m_hDC;
	HFONT	 m_hFont;
	HFONT	 m_hbkFont;
};

// -------------------------------------------------------------
// inlines font class
// -------------------------------------------------------------
inline int t_font::get_baseline() const
{
	return m_baseline;
}

inline t_font_bitmap* t_font::get_character( t_uint8 character ) const
{
	assert( m_characters );

	int offset = character - m_first_character;

	if (offset < 0 || offset >= m_size) {
#ifndef NDEBUG
		// Make a pain of ourselves (once) so the text gets fixed.
		// The problem is an illegal character in the input string.
		static bool have_fired = false;
		if (!have_fired) {
			assert( false );
			have_fired = true;
		}
#endif
		offset = 0;			// Work around the problem and move on.
	}

	return &m_characters[offset];
}

inline int t_font::get_first_character() const
{
	return m_first_character;
}

inline int t_font::get_height() const
{
	return m_height;
}

inline int t_font::get_last_character() const
{
	return m_first_character + m_size - 1;
}

inline int t_font::get_max_width() const
{
	return m_max_width;
}

inline t_screen_rect t_font::get_rect( char const* text ) const
{
	return t_screen_rect(0,0, get_width(text), m_height );
}

inline int t_font::get_size() const
{
	return m_size;
}

template <>
struct t_resource_traits<t_font>
{
	static char const prefix[];
	static char const extension[];
};

inline bool read( std::streambuf& buffer, t_font& font )
{
	return font.read( buffer );
}

inline bool write( std::streambuf& buffer, t_font const& font )
{
	return font.write( buffer );
}

#endif // FONT_H_INCLUDED